#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<iostream>
#include<string>
#include<fcntl.h>
#include<sys/stat.h>


#define MAXSIZE 100

using namespace std;

//定义重定向的方式
#define NoneRed   0
#define InputRed  1
#define OutputRed 2
#define AppendRed 3
//记录当前指令重定向方式和被操作文件
int Red_type = NoneRed;
char* filename;

//命令行参数 + 参数个数
int myargc;
char* myargv[MAXSIZE];

//记录命令行输入的指令
char buff[MAXSIZE];
//记录进程当前工作路径
char workingDr[MAXSIZE];
//exitNumber
int lastExitNumber;

//定义宏函数
#define removespace(start) do{while(isspace(*start)) start++;}while(0)


char* GetUser()
{
  char* user = getenv("USER");
  return user;
}
char* GetHostName()
{
  char* hostname = getenv("HOSTNAME");
  return hostname;
}
string GetPwd()
{
  //char* pwd = getenv("PWD");
  getcwd(workingDr,sizeof(workingDr));
  if(strcmp(workingDr,"/") == 0)
    return "/";

  string s(workingDr);
  int pos = s.rfind('/');

  return s.substr(pos + 1);
}

void init()
{
    printf("[%s@%s %s]# ",GetUser(),GetHostName(),GetPwd().c_str());
    fflush(stdout);
}
void getCommand()
{
    fgets(buff,sizeof buff,stdin);
    int len = strlen(buff);
    buff[len - 1] = '\0';
}

void parseCommand()
{
  //截取之前需要将重置数组
  memset(myargv,0,sizeof myargv);
  myargc = 0; 
  //使用字符串截取函数strtok
  const char* mysep = " #:";
  myargv[0] = strtok(buff,mysep);
  while((myargv[++myargc] = strtok(NULL,mysep)));
  myargv[myargc] = NULL;

 // printf("参数个数:%d\n",myargc);
 // for(int i = 0; myargv[i]; i++)
 // {
 //   printf("myargv[%d]->%s\n",i,myargv[i]);
 // }
}
void  executeCommand()
{
  pid_t id = fork();
  if(id < 0)
  {
    printf("fork failed!");
  }
  else if(id == 0)
  {//child
    if(Red_type == 1)//输入重定向
    {
      int fd = open(filename,O_RDONLY);//输入重定向这个文件肯定已经存在了
      dup2(fd,InputRed);
    }
    else if(Red_type == 2)//输出重定向
    {
      int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);//输入重定向这个文件肯定已经存在了
      dup2(fd,OutputRed);
    }
    else if(Red_type == 3)//追加重定向
    {
      int fd = open(filename, O_WRONLY | O_CREAT  |O_APPEND, 0666);//输入重定向这个文件肯定已经存在了
      dup2(fd,AppendRed);
    }
    else{
      //bug
    }
    execvp(myargv[0],myargv);
    exit(1);//看替换是否成功
  }
  else{//father
    int status = 0;
    pid_t pid = waitpid(id,&status,0);
    if(pid > 0)
    {
      //printf("wait child sucess!\n");
      //设置退出码
      lastExitNumber = WEXITSTATUS(status);
    }
  }
}
int checkBulitInExecute()
{
  if(strcmp(myargv[0],"cd") == 0)
  {
    if(myargc == 2)
    {
      chdir(myargv[1]);
      //因为修改当前工作路径不会修改环境变量,不能通过环境变量的方式来找当前工作路径
      //存储此时的新路径
     // getcwd(workingDr,sizeof(workingDr));
      lastExitNumber = 0;
      return 1;
    }
  }
  else if(strcmp(myargv[0],"echo") == 0)
  {
    if(myargc == 2)
    {
      if(myargv[1][0] == '$')//识别$为类解引用操作
      {
        if(strcmp(myargv[1] + 1,"?") == 0)
        {
          printf("ExitNumber:%d\n",lastExitNumber);
          lastExitNumber = 0;//正确执行打印操作
        }
        else if(strcmp(myargv[1] + 1,"PATH") == 0)
        {
          printf("%s\n",getenv("PATH"));
          lastExitNumber = 0;
        }
        return 1;
      }
      else if(strcmp("myargv[1]", filename))//echo 输出文件内容,有问题还
      {
        printf("filename文件内容:%s\n",filename);
      }
    }
  }
  return 0;
}

void checkRed()
{
  //初始化
  Red_type = NoneRed;
  filename = NULL;
  char* start = buff;
  char* end = buff + strlen(buff);
  //ls -a -l >> file.txt
  while(start < end)
  {
    if(*start == '>')
    {
      if(*(start + 1) == '>')//追加重定向
      {
          *start = '\0';
          ++start;
          *start = '\0';
          start++;//走到有关重定向操作符的下一个位置
          removespace(start);//消除文件名前面的空格
          Red_type = AppendRed;
          filename = start;
          break;
      }
      //输出重定向
      *start = '\0';
      start++;//走到有关重定向操作的下一个位置
      removespace(start);
      Red_type = OutputRed;
      filename = start;
    }
    else if(*start == '<')//输入重定向
    {
      *start = '\0';
      start++;//走到有关重定向操作的下一个位置
      removespace(start);
      Red_type = InputRed;
      filename = start;
    }
    else{
      start++;
    }
  }

}
int main()
{
  while(1)
  {
    //1:初始化界面
    init();
    //2:从键盘中获取输入
    getCommand();
    // "ls -a -l" -> "ls" "-a" "-l"
    //ls -a -l >> file.txt -> "ls -a -l" "file.txt"
    //涉及重定向,分离指令 + 被操作文件
    //3.分离指令 + filename
    checkRed();
    printf("command:%s\n",buff);
    printf("red_type:%d\n",Red_type);
    printf("filname:%s\n",filename);
    //4:解析数据
    parseCommand();
    //5:是否是内建指令
    if(checkBulitInExecute())
    {
      continue;
    }
    //6:运行程序
    executeCommand();
  }
  return 0;
}
